home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / program / 332 / top / peep2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-08-27  |  18.3 KB  |  830 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Tony Andrews
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  */
  11.  
  12. /*
  13.  * 2-instruction peephole optimizations
  14.  */
  15.  
  16. #include "top.h"
  17.  
  18.  
  19. /*
  20.  * ipeep2(bp, i1) - look for 2-instruction optimizations at the given inst.
  21.  */
  22. static    bool
  23. ipeep2(bp, i1)
  24. BLOCK    *bp;
  25. register INST    *i1;
  26. {
  27.     register INST    *i2;        /* the next instruction */
  28.     register INST    *ti2;        /* "temporary" next inst */
  29.  
  30.     register int    op1, op2;    /* opcodes, for speed */
  31.     register int    sm1, dm1;    /* src, dst amode inst. 1 */
  32.     register int    dr1;        /* dest. reg. inst. 1 */
  33.  
  34.     i2  = i1->next;
  35.     op1 = i1->opcode;
  36.     op2 = i2->opcode;
  37.  
  38.     sm1 = i1->src.amode;
  39.     dm1 = i1->dst.amode;
  40.     dr1 = i1->dst.areg;
  41.  
  42.     /*
  43.      * Avoid stack fix-ups after a call if possible.
  44.      */
  45.  
  46.     /*
  47.      *    addq    #4,sp
  48.      *    ... stuff that doesn't use SP ...
  49.      *    move.l    ?,-(sp)        =>    move.l    ?,(sp)
  50.      */
  51.     if (op1 == ADDQ && sm1 == IMM && i1->src.disp == 4 &&
  52.         dm1 == REG && dr1 == SP) {
  53.  
  54.         ti2 = i2;
  55.         while (!uses(ti2, SP)) {
  56.             if (ti2->next == NULL)
  57.                 goto end2;
  58.             ti2 = ti2->next;
  59.         }
  60.  
  61.         if (ti2->opcode == MOVE && ti2->flags == LENL &&
  62.             ti2->dst.amode == (REGI|DEC) && ti2->dst.areg == SP) {
  63.                 ti2->dst.amode = REGI;
  64.                 delinst(bp, i1);
  65.                 DBG(printf("%d ", __LINE__))
  66.                 return TRUE;
  67.         }
  68.     }
  69. end2:
  70.  
  71.     /*
  72.      *    addq    #2,sp
  73.      *    ... stuff that doesn't use SP ...
  74.      *    move.w    ?,-(sp)        =>    move.w    ?,(sp)
  75.      */
  76.     if (op1 == ADDQ && sm1 == IMM && i1->src.disp == 2 &&
  77.         dm1 == REG && dr1 == SP) {
  78.  
  79.         ti2 = i2;
  80.         while (!uses(ti2, SP)) {
  81.             if (ti2->next == NULL)
  82.                 goto end3;
  83.             ti2 = ti2->next;
  84.         }
  85.  
  86.         if (ti2->opcode == MOVE && ti2->flags == LENW &&
  87.             ti2->dst.amode == (REGI|DEC) && ti2->dst.areg == SP) {
  88.                 ti2->dst.amode = REGI;
  89.                 delinst(bp, i1);
  90.                 DBG(printf("%d ", __LINE__))
  91.                 return TRUE;
  92.         }
  93.     }
  94. end3:
  95.  
  96.     /*
  97.      * Avoid "tst" instructions following instructions that
  98.      * set the Z flag.
  99.      */
  100.  
  101.     /*
  102.      *    move.x    X, Y        =>    move.x    X, Y
  103.      *    tst.x    X or Y            ...deleted...
  104.      *    beq/bne                beq/bne
  105.      *
  106.      *    Where Y is not An, because "movea" doesn't set the
  107.      *    zero flag.
  108.      */
  109.     if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
  110.         op1 == MOVE && op2 == TST &&
  111.         i1->flags == i2->flags) {
  112.  
  113.         /*
  114.          * If pre-decrement is set on the dest. of the move,
  115.          * don't let that screw up the operand comparison.
  116.          */
  117.         if (dm1 & DEC)
  118.             dm1 &= ~DEC;
  119.  
  120.         if (opeq(&i1->dst, &i2->src) || opeq(&i1->src, &i2->src)) {
  121.             if (dm1 != REG || ISD(dr1)) {
  122.                     delinst(bp, i2);
  123.                     DBG(printf("%d ", __LINE__))
  124.                     return TRUE;
  125.             }
  126.         }
  127.     }
  128.  
  129.     /*
  130.      *    and.x    X, Y        =>    and.x    X, Y
  131.      *    tst.x    X or Y            ...deleted...
  132.      *    beq/bne                beq/bne
  133.      *
  134.      *    Where Y is not An, because "movea" doesn't set the
  135.      *    zero flag.
  136.      */
  137.     if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
  138.         op1 == AND && op2 == TST &&
  139.         i1->flags == i2->flags) {
  140.  
  141.         /*
  142.          * If pre-decrement is set on the dest. of the move,
  143.          * don't let that screw up the operand comparison.
  144.          */
  145.         if (dm1 & DEC)
  146.             dm1 &= ~DEC;
  147.  
  148.         if (opeq(&i1->dst, &i2->src) || opeq(&i1->src, &i2->src)) {
  149.             if (dm1 != REG || ISD(dr1)) {
  150.                     delinst(bp, i2);
  151.                     DBG(printf("%d ", __LINE__))
  152.                     return TRUE;
  153.             }
  154.         }
  155.     }
  156.  
  157.     /*
  158.      *    ext.x    Dn        =>    ext.x    Dn
  159.      *    tst.x    Dn            ...deleted...
  160.      *    beq/bne                beq/bne
  161.      *
  162.      *    Where Y is not An, because "movea" doesn't set the
  163.      *    zero flag.
  164.      */
  165.     if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
  166.         op1 == EXT && op2 == TST &&
  167.         i1->flags == i2->flags) {
  168.  
  169.         if (sm1 == REG && ISD(i1->src.areg) &&
  170.             i2->src.amode == REG && i1->src.areg == i2->src.areg) {
  171.                 delinst(bp, i2);
  172.                 DBG(printf("%d ", __LINE__))
  173.                 return TRUE;
  174.         }
  175.     }
  176.  
  177.     /*
  178.      *    move.?    X, Dn        =>    move.?    X, Dn
  179.      *    ext.?    Dn            ...deleted...
  180.      *    beq/bne                beq/bne
  181.      *
  182.      *    Where Dn is dead after the "ext".
  183.      */
  184.     if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
  185.         op1 == MOVE && op2 == EXT) {
  186.  
  187.         if (dm1 == REG && ISD(dr1) &&
  188.             i2->src.amode == REG && dr1 == i2->src.areg) {
  189.             if ((i2->live & RM(i2->src.areg)) == 0) {
  190.                 delinst(bp, i2);
  191.                     DBG(printf("%d ", __LINE__))
  192.                  return TRUE;
  193.             }
  194.         }
  195.     }
  196.  
  197.     /*
  198.      *    ext.l    Dm        =>    ...deleted...
  199.      *    tst.l    Dm            tst.w    Dm
  200.      *
  201.      *    where Dm is dead after the "tst".
  202.      */
  203.     if (op1 == EXT && op2 == TST &&
  204.         ((i1->flags & LENL) != 0) &&  ((i2->flags & LENL) != 0) &&
  205.         (i1->src.areg == i2->src.areg) && ISD(i1->src.areg)) {
  206.  
  207.         if ((i2->live & RM(i2->src.areg)) == 0) {
  208.             i2->flags = LENW;
  209.             delinst(bp, i1);
  210.                 DBG(printf("%d ", __LINE__))
  211.             return TRUE;
  212.         }
  213.     }
  214.  
  215.     /*
  216.      *    ext.l    Dm        =>    ...deleted...
  217.      *    ???    N(An,Dm.l), ??        ???    N(An,Dm.w), ??
  218.      *
  219.      *    Where Dm is dead
  220.      */
  221.     if ((op1 == EXT) && (i1->flags & LENL) &&
  222.         (i2->src.amode == (REGIDX|XLONG)) &&
  223.         (i1->src.areg == i2->src.ireg)) {
  224.  
  225.         if ((i2->live & RM(i1->src.areg)) == 0) {
  226.             i2->src.amode &= ~XLONG;
  227.             delinst(bp, i1);
  228.                 DBG(printf("%d ", __LINE__))
  229.             return TRUE;
  230.         }
  231.     }
  232.  
  233.     /*
  234.      *    ext.l    Dm        =>    ...deleted...
  235.      *    ???    ??, N(An,Dm.l)        ???    ??, N(An,Dm.w)
  236.      *
  237.      *    Where Dm is dead
  238.      */
  239.     if ((op1 == EXT) && (i1->flags & LENL) &&
  240.         (i2->dst.amode == (REGIDX|XLONG)) &&
  241.         (i1->src.areg == i2->dst.ireg)) {
  242.  
  243.         if ((i2->live & RM(i1->src.areg)) == 0) {
  244.             i2->dst.amode &= ~XLONG;
  245.             delinst(bp, i1);
  246.                 DBG(printf("%d ", __LINE__))
  247.             return TRUE;
  248.         }
  249.     }
  250.  
  251.     /*
  252.      * Avoid intermediate registers.
  253.      */
  254.  
  255.     /*
  256.      *    move.x    X, Dm        =>    INST.x    X, Dn
  257.      *    INST.x    Dm, Dn
  258.      *
  259.      *    where Dm is dead, and INST is one of: add, sub, and, or, cmp
  260.      */
  261.     if ((op1 == MOVE) &&
  262.         ((op2==ADD)||(op2==SUB)||(op2==AND)||(op2==OR)||(op2==CMP)) &&
  263.         (i1->flags == i2->flags) &&
  264.         (dm1 == REG) && ISD(dr1) &&
  265.         (i2->src.amode == REG) && ISD(i2->src.areg) &&
  266.         (dr1 == i2->src.areg) &&
  267.         (i2->dst.amode == REG) && ISD(i2->dst.areg)) {
  268.  
  269.         if ((i2->live & RM(i2->src.areg)) == 0) {
  270.  
  271.             i1->opcode = i2->opcode;
  272.             i1->dst.areg = i2->dst.areg;
  273.  
  274.             delinst(bp, i2);
  275.                 DBG(printf("%d ", __LINE__))
  276.             return TRUE;
  277.         }
  278.     }
  279.  
  280.     /*
  281.      * Silly moves
  282.      */
  283.  
  284.     /*
  285.      *    move.x    X, Y        =>    move.x    X, Y
  286.      *    move.x    Y, X
  287.      */
  288.     if ((op1 == MOVE) && (op2 == MOVE) &&
  289.         (i1->flags == i2->flags) &&
  290.         opeq(&i1->src, &i2->dst) && opeq(&i1->dst, &i2->src) &&
  291.         ((i1->src.amode & (INC|DEC)) == 0) &&
  292.         ((i1->dst.amode & (INC|DEC)) == 0)) {
  293.  
  294.              delinst(bp, i2);
  295.             DBG(printf("%d ", __LINE__))
  296.              return TRUE;
  297.     }
  298.  
  299.     /*
  300.      *    move.x    X, Y        =>    move.x    X, Rn
  301.      *    move.x    Y, Rn            move.x    Rn, Y
  302.      *
  303.      *    where Y isn't INC or DEC, and isn't register direct
  304.      */
  305.     if ((op1 == MOVE) && (op2 == MOVE) && (i2->dst.amode == REG) &&
  306.         opeq(&i1->dst, &i2->src) && ((i1->dst.amode & (INC|DEC)) == 0) &&
  307.         (i1->flags == i2->flags) && (i1->dst.amode != REG)) {
  308.  
  309.         freeop(&i1->dst);
  310.         i1->dst = i2->dst;
  311.         i2->dst = i2->src;
  312.         i2->src = i1->dst;
  313.  
  314.             DBG(printf("%d ", __LINE__))
  315.         return TRUE;
  316.     }
  317.  
  318.     /*
  319.      *    move.x    Dm, X        =>    move.x    Dm, X
  320.      *    move.x    X, Y            move.x    Dm, Y
  321.      *
  322.      * Where 'x' is the same, and 'X' has no side-effects.
  323.      */
  324.     if ((op1 == MOVE) && (op2 == MOVE) &&
  325.         (sm1 == REG) && ISD(i1->src.areg) &&
  326.         (i1->flags == i2->flags) && opeq(&i1->dst, &i2->src) &&
  327.         ((dm1 & (DEC|INC)) == 0)) {
  328.  
  329.  
  330.         freeop(&i2->src);
  331.         i2->src = i1->src;
  332.             DBG(printf("%d ", __LINE__))
  333.              return TRUE;
  334.     }
  335.  
  336.     /*
  337.      *    move.?    Rm, Rn        =>    move.?    Rm, Rn
  338.      *    ... stuff ...            ... stuff ...
  339.      *    move.?    Rm, Rn
  340.      *
  341.      *    where "stuff" doesn't set Rm or Rn. Also make sure that
  342.      *    the second move isn't followed by a conditional branch.
  343.      *    In that case leave everything alone since the branch
  344.      *    probably relies on flags set by the move.
  345.      */
  346.     if ((op1 == MOVE) && (sm1 == REG) && (dm1 == REG)) {
  347.         int    s1 = i1->src.areg;    /* source reg of inst. 1 */
  348.  
  349.         ti2 = i2;
  350.         while (ti2 != NULL && !sets(ti2, s1) && !sets(ti2, dr1)) {
  351.  
  352.             if ((ti2->opcode==MOVE) && (i1->flags==ti2->flags) &&
  353.                 (ti2->src.amode==REG) && (ti2->dst.amode==REG) &&
  354.                 (i1->src.areg == ti2->src.areg) &&
  355.                 (i1->dst.areg == ti2->dst.areg) &&
  356.                 ((bp->last != ti2) || (bp->bcond == NULL)) ) {
  357.  
  358.                      delinst(bp, ti2);
  359.                     DBG(printf("%d ", __LINE__))
  360.                      return TRUE;
  361.             }
  362.             ti2 = ti2->next;
  363.         }
  364.     }
  365.  
  366.     /*
  367.      *    move.l    Am, Dn        =>    move.l    Am, Ao
  368.      *    ... stuff ...            ... stuff ...
  369.      *    move.l    Dn, Ao
  370.      *
  371.      *    where "stuff" doesn't set Dn.
  372.      */
  373.     if ((op1 == MOVE) && (i1->flags == LENL) &&
  374.         (sm1 == REG) && ISA(i1->src.areg) &&
  375.         (dm1 == REG) && ISD(dr1)) {
  376.  
  377.         ti2 = i2;
  378.         while (!sets(ti2, dr1)) {
  379.  
  380.             if ((ti2->opcode == MOVE) && (ti2->flags == LENL) &&
  381.                 (ti2->src.amode == REG) && ISD(ti2->src.areg) &&
  382.                 (ti2->dst.amode == REG) && ISA(ti2->dst.areg) &&
  383.                 (dr1 == ti2->src.areg)) {
  384.     
  385.                 /*
  386.                  * If the intermediate register isn't dead,
  387.                  * then we have to keep using it.
  388.                  */
  389.                 if ((ti2->live & RM(ti2->src.areg)) != 0)
  390.                     goto end14;
  391.     
  392.                 i1->dst.areg = ti2->dst.areg;
  393.     
  394.                      delinst(bp, ti2);
  395.                     DBG(printf("%d ", __LINE__))
  396.                      return TRUE;
  397.             }
  398.  
  399.             if (ti2->next == NULL)
  400.                 goto end14;
  401.  
  402.             ti2 = ti2->next;
  403.         }
  404.     }
  405. end14:
  406.  
  407.     /*
  408.      *    move.l    Dm, An        =>    move.l    Dm, Ao
  409.      *    lea    (An), Ao
  410.      *
  411.      *    where An is dead
  412.      */
  413.     if ((op1 == MOVE) && (op2 == LEA) &&
  414.         (sm1 == REG) && ISD(i1->src.areg) &&
  415.         (dm1 == REG) && ISA(dr1) &&
  416.         (i2->src.amode == REGI) && (i2->dst.amode == REG) &&
  417.         ISA(i2->dst.areg) && (dr1 == i2->src.areg)) {
  418.  
  419.         if ((i2->live & RM(i2->src.areg)) == 0) {
  420.  
  421.             i1->dst.areg = i2->dst.areg;
  422.  
  423.             delinst(bp, i2);
  424.                 DBG(printf("%d ", __LINE__))
  425.             return TRUE;
  426.         }
  427.     }
  428.  
  429.     /*
  430.      *    lea    X, An        =>    lea    X, Ao
  431.      *    lea    (An), Ao
  432.      *
  433.      *    where An is dead
  434.      */
  435.     if ((op1 == LEA) && (op2 == LEA) &&
  436.         (i2->src.amode == REGI) && (dr1 == i2->src.areg)) {
  437.  
  438.         if ((i2->live & RM(i2->src.areg)) == 0) {
  439.  
  440.             i1->dst.areg = i2->dst.areg;
  441.  
  442.             delinst(bp, i2);
  443.                 DBG(printf("%d ", __LINE__))
  444.             return TRUE;
  445.         }
  446.     }
  447.  
  448.     /*
  449.      *    lea    N(Am), Am    =>
  450.      *    ?    (Am)[,...]        ?    N(Am)[,...]
  451.      *
  452.      *    Where Am is either dead after the second instruction or
  453.      *    is a direct destination of the second instruction.
  454.      */
  455.     if ((op1 == LEA) && (i1->src.amode == REGID) &&
  456.         (i1->src.areg == i1->dst.areg) &&
  457.         (i2->src.amode == REGI) && (i1->dst.areg == i2->src.areg)) {
  458.  
  459.         if (((i2->live & RM(i2->src.areg)) == 0) ||
  460.            ((i2->dst.amode == REG) && (i2->dst.areg == i2->src.areg))) {
  461.             i2->src.amode = REGID;
  462.             i2->src.disp = i1->src.disp;
  463.             delinst(bp, i1);
  464.                 DBG(printf("%d ", __LINE__))
  465.             return TRUE;
  466.         }
  467.     }
  468.  
  469.     /*
  470.      *    lea    N(Am), Am    =>
  471.      *    ?    X, (Am)            ?    X, N(Am)
  472.      *
  473.      *    Where X doesn't reference Am, and Am is dead after the
  474.      *    second instruction.
  475.      */
  476.     if ((op1 == LEA) && (i1->src.amode == REGID) &&
  477.         (i1->src.areg == i1->dst.areg) &&
  478.         (i2->dst.amode == REGI) && (i1->dst.areg == i2->dst.areg)) {
  479.  
  480.         if (((i2->live & RM(i2->dst.areg)) == 0) &&
  481.             ((i2->src.amode == IMM) || (i2->src.amode == ABS) ||
  482.              (i2->src.areg != i2->dst.areg))) {
  483.             i2->dst.amode = REGID;
  484.             i2->dst.disp = i1->src.disp;
  485.             delinst(bp, i1);
  486.                 DBG(printf("%d ", __LINE__))
  487.             return TRUE;
  488.         }
  489.     }
  490.  
  491.     /*
  492.      *    lea    X, Am        =>    ...deleted...
  493.      *    clr.x    (Am)            clr.x    X
  494.      *
  495.      *    where Am is dead
  496.      */
  497.     if ((op1 == LEA) && (op2 == CLR) && i2->src.amode == REGI &&
  498.         (i1->dst.areg == i2->src.areg)) {
  499.  
  500.         if ((i2->live & RM(i2->src.areg)) == 0) {
  501.             i2->src = i1->src;
  502.     
  503.             delinst(bp, i1);
  504.                 DBG(printf("%d ", __LINE__))
  505.             return TRUE;
  506.         }
  507.     }
  508.  
  509.     /*
  510.      *    lea    X, Am        =>    ...deleted...
  511.      *    move.x    Y, (Am)            move.x    Y, X
  512.      *
  513.      *    where Am is dead
  514.      */
  515.     if ((op1 == LEA) && (op2 == MOVE) && i2->dst.amode == REGI &&
  516.         (i1->dst.areg == i2->dst.areg)) {
  517.  
  518.         if ((i2->live & RM(i2->dst.areg)) == 0) {
  519.             i2->dst = i1->src;
  520.  
  521.             delinst(bp, i1);
  522.                 DBG(printf("%d ", __LINE__))
  523.             return TRUE;
  524.         }
  525.     }
  526.  
  527.     /*
  528.      *    lea    X, Am        =>    ...deleted...
  529.      *    move.x    (Am), Y            move.x    X, Y
  530.      *
  531.      *    where Am is dead
  532.      */
  533.     if ((op1 == LEA) && (op2 == MOVE) && i2->src.amode == REGI &&
  534.         (i1->dst.areg == i2->src.areg)) {
  535.  
  536.         if ((i2->live & RM(i2->src.areg)) == 0) {
  537.             i2->src = i1->src;
  538.  
  539.             delinst(bp, i1);
  540.                 DBG(printf("%d ", __LINE__))
  541.             return TRUE;
  542.         }
  543.     }
  544.  
  545.     /*
  546.      *    move.x    Dm, X        =>    move.x    Dm, X
  547.      *    cmp.x    #N, X            cmp.x    #N, Dm
  548.      *
  549.      *    Where X isn't register direct.
  550.      *
  551.      *    Since X generally references memory, we can compare
  552.      *    with the register faster.
  553.      */
  554.     if ((op1 == MOVE) && (op2 == CMP) &&
  555.         (i1->flags == i2->flags) && (i2->src.amode == IMM) &&
  556.         (sm1 == REG) && ISD(i1->src.areg) && (dm1 != REG) &&
  557.         opeq(&i1->dst, &i2->dst) && ((dm1 & (INC|DEC)) == 0)) {
  558.  
  559.         freeop(&i2->dst);
  560.         i2->dst.amode = REG;
  561.         i2->dst.areg = i1->src.areg;
  562.  
  563.             DBG(printf("%d ", __LINE__))
  564.         return TRUE;
  565.     }
  566.  
  567.  
  568.     /*
  569.      * Try to use register indirect w/ displacement and/or index
  570.      */
  571.  
  572.     /*
  573.      *    add.l    Am, Dn        =>    lea    0(Am,Dn.l), Ao
  574.      *    move.l    Dn, Ao
  575.      *
  576.      *    where Dn is dead
  577.      */
  578.     if ((op1 == ADD) && (op2 == MOVE) &&
  579.         (sm1 == REG) && ISA(i1->src.areg) &&
  580.         (dm1 == REG) && ISD(dr1) &&
  581.         (i2->src.amode == REG) && ISD(i2->src.areg) &&
  582.         (i2->dst.amode == REG) && ISA(i2->dst.areg) &&
  583.         (dr1 == i2->src.areg) &&
  584.         (i1->flags & LENL) && (i2->flags & LENL)) {
  585.  
  586.         if ((i2->live & RM(i2->src.areg)) == 0) {
  587.  
  588.             i2->opcode = LEA;
  589.             i2->flags = 0;
  590.  
  591.             i2->src.amode = REGIDX|XLONG;
  592.             i2->src.disp = 0;
  593.             i2->src.areg = i1->src.areg;
  594.             i2->src.ireg = dr1;
  595.  
  596.                 delinst(bp, i1);
  597.                 DBG(printf("%d ", __LINE__))
  598.                 return TRUE;
  599.         }
  600.     }
  601.  
  602.     /*
  603.      *    add.l    Dm, An        =>    move.x    0(An,Dm.l), Do
  604.      *    move.x    (An), Do
  605.      *
  606.      *    where An is dead
  607.      */
  608.     if ((op1 == ADD) && (op2 == MOVE) &&
  609.         (sm1 == REG) && ISD(i1->src.areg) &&
  610.         (dm1 == REG) && ISA(dr1) &&
  611.         (i2->src.amode == REGI)&& ISA(i2->src.areg) &&
  612.         (i2->dst.amode == REG) && ISD(i2->dst.areg) &&
  613.         (dr1 == i2->src.areg) && (i1->flags & LENL)) {
  614.  
  615.         if ((i2->live & RM(i2->src.areg)) == 0) {
  616.  
  617.             i2->src.amode = REGIDX|XLONG;
  618.             i2->src.disp = 0;
  619.             i2->src.ireg = i1->src.areg;
  620.  
  621.                 delinst(bp, i1);
  622.                 DBG(printf("%d ", __LINE__))
  623.                 return TRUE;
  624.         }
  625.     }
  626.  
  627.     /*
  628.      *    lea    N(Am), An    =>    lea    N(Am,Do.l), An
  629.      *    add.l    Do, An
  630.      *
  631.      */
  632.     if ((op1 == LEA) && (op2 == ADD) &&
  633.         (sm1 == REGID) &&
  634.         (i2->src.amode == REG) && ISD(i2->src.areg) &&
  635.         (i2->dst.amode == REG) && ISA(i2->dst.areg) &&
  636.         (dr1 == i2->dst.areg) && D8OK(i1->src.disp)) {
  637.  
  638.         i1->src.amode = REGIDX|XLONG;
  639.         i1->src.ireg = i2->src.areg;
  640.         delinst(bp, i2);
  641.             DBG(printf("%d ", __LINE__))
  642.         return TRUE;
  643.     }
  644.  
  645.  
  646.  
  647.     /*
  648.      * Try to use the pre-decrement and post-increment modes
  649.      * whenever possible.
  650.      */
  651.  
  652.     /*
  653.      *    sub.l    #1, Am
  654.      *    ... stuff ...
  655.      *    ???.b    ..(Am)..    =>    ???.b    ..-(Am)..
  656.      *
  657.      *    Nothing in "stuff" can refer to Am.
  658.      */
  659.     if ((op1 == SUB) && (i1->flags & LENL) &&
  660.         (sm1 == IMM) && (i1->src.disp == 1) &&
  661.         (dm1 == REG) && ISA(dr1)) {
  662.  
  663.         while (i2 != NULL) {
  664.  
  665.             if (i2->src.amode == REGI && i2->src.areg == dr1) {
  666.  
  667.                 if ((i2->flags & LENB) == 0)
  668.                     goto end24;
  669.  
  670.                 i2->src.amode |= DEC;
  671.  
  672.                     delinst(bp, i1);
  673.                     DBG(printf("%d ", __LINE__))
  674.                     return TRUE;
  675.             }
  676.             if (i2->dst.amode == REGI && i2->dst.areg == dr1) {
  677.  
  678.                 if ((i2->flags & LENB) == 0)
  679.                     goto end24;
  680.  
  681.                 i2->dst.amode |= DEC;
  682.  
  683.                     delinst(bp, i1);
  684.                     DBG(printf("%d ", __LINE__))
  685.                     return TRUE;
  686.             }
  687.  
  688.             if (uses(i2, RM(dr1)))
  689.                 goto end24;
  690.  
  691.             if (i2->next == NULL)
  692.                 goto end24;
  693.             else
  694.                 i2 = i2->next;
  695.  
  696.         }
  697.     }
  698. end24:
  699.  
  700.     /*
  701.      *    sub.l    #2, Am
  702.      *    ... stuff ...
  703.      *    ???.w    ..(Am)..    =>    ???.w    ..-(Am)..
  704.      *
  705.      *    Nothing in "stuff" can refer to Am.
  706.      */
  707.     if ((op1 == SUB) && (i1->flags & LENL) &&
  708.         (sm1 == IMM) && (i1->src.disp == 2) &&
  709.         (dm1 == REG) && ISA(dr1)) {
  710.  
  711.         while (i2 != NULL) {
  712.  
  713.             if (i2->src.amode == REGI && i2->src.areg == dr1) {
  714.  
  715.                 if ((i2->flags & LENW) == 0)
  716.                     goto end26;
  717.  
  718.                 i2->src.amode |= DEC;
  719.  
  720.                     delinst(bp, i1);
  721.                     DBG(printf("%d ", __LINE__))
  722.                     return TRUE;
  723.             }
  724.             if (i2->dst.amode == REGI && i2->dst.areg == dr1) {
  725.  
  726.                 if ((i2->flags & LENW) == 0)
  727.                     goto end26;
  728.  
  729.                 i2->dst.amode |= DEC;
  730.  
  731.                     delinst(bp, i1);
  732.                     DBG(printf("%d ", __LINE__))
  733.                     return TRUE;
  734.             }
  735.  
  736.             if (uses(i2, RM(dr1)))
  737.                 goto end26;
  738.  
  739.             if (i2->next == NULL)
  740.                 goto end26;
  741.             else
  742.                 i2 = i2->next;
  743.  
  744.         }
  745.     }
  746. end26:
  747.  
  748.     /*
  749.      *    sub.l    #4, Am
  750.      *    ... stuff ...
  751.      *    ???.l    ..(Am)..    =>    ???.l    ..-(Am)..
  752.      *
  753.      *    Nothing in "stuff" can refer to Am.
  754.      */
  755.     if ((op1 == SUB) && (i1->flags & LENL) &&
  756.         (sm1 == IMM) && (i1->src.disp == 4) &&
  757.         (dm1 == REG) && ISA(dr1)) {
  758.  
  759.         while (i2 != NULL) {
  760.  
  761.             if (i2->src.amode == REGI && i2->src.areg == dr1) {
  762.  
  763.                 if ((i2->flags & LENL) == 0)
  764.                     goto end28;
  765.  
  766.                 i2->src.amode |= DEC;
  767.  
  768.                     delinst(bp, i1);
  769.                     DBG(printf("%d ", __LINE__))
  770.                     return TRUE;
  771.             }
  772.             if (i2->dst.amode == REGI && i2->dst.areg == dr1) {
  773.  
  774.                 if ((i2->flags & LENL) == 0)
  775.                     goto end28;
  776.  
  777.                 i2->dst.amode |= DEC;
  778.  
  779.                     delinst(bp, i1);
  780.                     DBG(printf("%d ", __LINE__))
  781.                     return TRUE;
  782.             }
  783.  
  784.             if (uses(i2, RM(dr1)))
  785.                 goto end28;
  786.  
  787.             if (i2->next == NULL)
  788.                 goto end28;
  789.             else
  790.                 i2 = i2->next;
  791.  
  792.         }
  793.     }
  794. end28:
  795.  
  796.     return FALSE;
  797. }
  798.  
  799. /*
  800.  * peep2(bp) - scan blocks starting at 'bp'
  801.  */
  802. bool
  803. peep2(bp)
  804. register BLOCK    *bp;
  805. {
  806.     register INST    *ip;
  807.     register bool    changed = FALSE;
  808.  
  809.     DBG(printf("p2 :"))
  810.  
  811.     for (; bp != NULL ;bp = bp->next) {
  812.         for (ip = bp->first; ip != NULL && ip->next != NULL ;) {
  813.             if (ipeep2(bp, ip)) {
  814.                 changed = TRUE;
  815.                 s_peep2++;
  816.                 bprep(bp);
  817.                 /*
  818.                  * If we had a match, then either instruction
  819.                  * may have been deleted, so the safe thing to
  820.                  * do is to go to the next block.
  821.                  */
  822.                 break;
  823.             } else
  824.                 ip = ip->next;
  825.         }
  826.     }
  827.     DBG(printf("\n"); fflush(stdout))
  828.     return changed;
  829. }
  830.